package com.monster.security.config;

import com.monster.security.filter.MonsterUsernamePasswordAuthenticationFilter;
import com.monster.security.handler.*;
import com.monster.security.service.impl.PasswordEncoderImpl;
import com.monster.security.service.impl.UserDetailsServiceImpl;
import com.monster.starter.core.common.config.http.HttpRequestConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * spring boot security安全配置
 * @author kuang
 */
@Configuration
@EnableWebSecurity
public class MonsterSecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     * 请求配置
     */
    @Autowired
    private HttpRequestConfig requestConfig;

    @Autowired
    private UserDetailsServiceImpl userDetailsService;
    @Autowired
    private PasswordEncoderImpl passwordEncoder;

    @Autowired
    private MonsterAuthenticationEntryPoint authenticationEntryPoint;
    @Autowired
    private MonsterAccessDeniedHandler accessDeniedHandler;
    @Autowired
    private MonsterLogoutSuccessHandler logoutSuccessHandler;


    @Autowired
    private MonsterUsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter;
    @Autowired
    private MonsterAuthenticationSuccessHandler authenticationSuccessHandler;
    @Autowired
    private MonsterAuthenticationFailureHandler authenticationFailureHandler;

    /**
     * 输出一个AuthenticationManager对象
     * @return AuthenticationManager对象并加入spring对象管理
     */
    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    /**
     * 对默认的认证进行覆盖
     * @param auth 权限认证对象
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
    }

    /**
     * 自定义请求头sessionid
     * @return
     */
    @Bean
    public HeaderHttpSessionIdResolver createHeaderHttpSessionIdResolver () {
        return new HeaderHttpSessionIdResolver(requestConfig.getAuthTokenName());
    }

    /**
     * http安全设置
     * @param http HttpSecurity
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 只要是登录用户都可以访问
        http.authorizeRequests()
                .antMatchers("/cipher/get","dict/*").permitAll()
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated()
                // 登录 允许所有用户
                .and().formLogin().loginProcessingUrl("/login").permitAll()
                // 异常处理(权限拒绝、登录失效等)
                .and().exceptionHandling()
                // 匿名用户访问无权限资源时的异常处理
                .authenticationEntryPoint(authenticationEntryPoint)
                //登录用户没有权限访问资源
                .accessDeniedHandler(accessDeniedHandler)
                // 登出
                .and().logout().permitAll().logoutSuccessHandler(logoutSuccessHandler);
        // 登录成功处理逻辑
        usernamePasswordAuthenticationFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler);
        // 登录失败处理逻辑
        usernamePasswordAuthenticationFilter.setAuthenticationFailureHandler(authenticationFailureHandler);

        // 自定义用户名和密码的获取方式
        http.addFilter(usernamePasswordAuthenticationFilter);
        http.cors().and().csrf().disable();
        // 禁用缓存
        http.headers().cacheControl();
        // Spring Security不会创建session，或使用session；
//        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }
}
